﻿using System;
using System.Collections.Generic;
using System.Text;
using NetworkLib.Utilities;

namespace PokemonBattle.BattleNetwork.Server
{
    internal static class PokemonBattleServerHelper
    {
        public static ByteArray BuildByteArray(EnumPokemonBattleMethods method, DataByteArray data)
        {
            ByteArray byteArray = new ByteArray();
            byteArray.WriteInt((int)method);
            if (data != null) data.Write(byteArray);
            return byteArray;
        }

        public static ByteArray LogonSuccess()
        {
            return BuildByteArray(EnumPokemonBattleMethods.Client_LogonSuccess_Hash, null);
        }

        public static ByteArray LogonFail(string message)
        {
            ByteArray byteArray = new ByteArray();

            byteArray.WriteInt((int)EnumPokemonBattleMethods.Client_LogonFail_Hash);
            byteArray.WriteUTF(message);

            return byteArray;
        }

        public static ByteArray ReceiveRandomSeed(int seed)
        {
            ByteArray byteArray = new ByteArray();

            byteArray.WriteInt((int)EnumPokemonBattleMethods.Client_ReceiveRandomSeed_Hash);
            byteArray.WriteInt(seed);

            return byteArray;
        }

        public static ByteArray ReceiveMove(PlayerMove move)
        {
            return BuildByteArray(EnumPokemonBattleMethods.Client_ReceiveMove_Hash, move);
        }

        public static ByteArray ReceiveTeam(byte position, string identity, ByteSequence team)
        {
            ByteArray byteArray = new ByteArray();

            byteArray.WriteInt((int)EnumPokemonBattleMethods.Client_ReceiveTeam_Hash);
            byteArray.WriteByte(position);

            byteArray.WriteUTF(identity);

            team.Write(byteArray);


            return byteArray;
        }

        public static ByteArray ReceiveRules(BattleRuleSequence rules)
        {
            return BuildByteArray(EnumPokemonBattleMethods.Client_ReceiveRules_Hash, rules);
        }

        public static ByteArray ReceiveTieMessage(string identity, TieMessage message)
        {
            ByteArray byteArray = new ByteArray();

            byteArray.WriteInt((int)EnumPokemonBattleMethods.Client_ReceiveTieMessage_Hash);
            byteArray.WriteUTF(identity);

            TieMessageHelper.WriteToByteArray(byteArray, message);


            return byteArray;
        }

        public static ByteArray Exit(string identity)
        {
            ByteArray byteArray = new ByteArray();

            byteArray.WriteInt((int)EnumPokemonBattleMethods.Client_Exit_Hash);
            byteArray.WriteUTF(identity);

            return byteArray;
        }

        public static ByteArray TimeUp(string identity)
        {
            ByteArray byteArray = new ByteArray();

            byteArray.WriteInt((int)EnumPokemonBattleMethods.Client_TimeUp_Hash);
            byteArray.WriteUTF(identity);

            return byteArray;
        }

        public static ByteArray RegistObsever(int identity)
        {
            ByteArray byteArray = new ByteArray();

            byteArray.WriteInt((int)EnumPokemonBattleMethods.Client_RegistObsever_Hash);
            byteArray.WriteInt(identity);


            return byteArray;
        }

        public static ByteArray ReceiveBattleInfo(BattleInfo info)
        {
            return BuildByteArray(EnumPokemonBattleMethods.Client_ReceiveBattleInfo_Hash, info);
        }

        public static ByteArray ReceiveBattleSnapshot(BattleSnapshot snapshot)
        {
            return BuildByteArray(EnumPokemonBattleMethods.Client_ReceiveBattleSnapshot_Hash, snapshot);
        }

        #region InterpretMessage

        public static bool InterpretMessage(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            byteArray.BypassHeader();
            var method = (EnumPokemonBattleMethods)byteArray.ReadInt();

            switch (method)
            {
                case EnumPokemonBattleMethods.Server_Logon_Hash:
                    return OnLogon(sessionID, byteArray, serverService);

                case EnumPokemonBattleMethods.Server_ReceiveMove_Hash:
                    return OnReceiveMove(sessionID, byteArray, serverService);

                case EnumPokemonBattleMethods.Server_ReceiveTeam_Hash:
                    return OnReceiveTeam(sessionID, byteArray, serverService);

                case EnumPokemonBattleMethods.Server_Exit_Hash:
                    return OnExit(sessionID, byteArray, serverService);

                case EnumPokemonBattleMethods.Server_TimeUp_Hash:
                    return OnTimeUp(sessionID, byteArray, serverService);

                case EnumPokemonBattleMethods.Server_ReceiveTieMessage_Hash:
                    return OnReceiveTieMessage(sessionID, byteArray, serverService);

                case EnumPokemonBattleMethods.Server_RegistObsever_Hash:
                    return OnRegistObsever(sessionID, byteArray, serverService);

                case EnumPokemonBattleMethods.Server_ReceiveBattleInfo_Hash:
                    return OnReceiveBattleInfo(sessionID, byteArray, serverService);

                case EnumPokemonBattleMethods.Server_ReceiveBattleSnapshot_Hash:
                    return OnReceiveBattleSnapshot(sessionID, byteArray, serverService);

            }

            byteArray.Rewind();
            return false;
        }

        private static bool OnLogon(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            string identity = byteArray.ReadUTF();
            BattleMode modeInfo = BattleModeHelper.ReadFromByteArray(byteArray);
            string versionInfo = byteArray.ReadUTF();

            serverService.OnLogon(sessionID, identity, modeInfo, versionInfo);
            return true;
        }

        private static bool OnReceiveMove(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            PlayerMove move = new PlayerMove();
            move.Read(byteArray);

            serverService.OnReceiveMove(sessionID, move);
            return true;
        }

        private static bool OnReceiveTeam(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            byte position = byteArray.ReadByte();
            string identity = byteArray.ReadUTF();
            ByteSequence team = new ByteSequence();
            team.Read(byteArray);

            serverService.OnReceiveTeam(sessionID, position, identity, team);
            return true;
        }

        private static bool OnExit(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            string identity = byteArray.ReadUTF();

            serverService.OnExit(sessionID, identity);
            return true;
        }

        private static bool OnTimeUp(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            string identity = byteArray.ReadUTF();

            serverService.OnTimeUp(sessionID, identity);
            return true;
        }

        private static bool OnReceiveTieMessage(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            string identity = byteArray.ReadUTF();
            TieMessage message = TieMessageHelper.ReadFromByteArray(byteArray);

            serverService.OnReceiveTieMessage(sessionID, identity, message);
            return true;
        }

        private static bool OnRegistObsever(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            int identity = byteArray.ReadInt();

            serverService.OnRegistObsever(sessionID, identity);
            return true;
        }

        private static bool OnReceiveBattleInfo(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            BattleInfo info = new BattleInfo();
            info.Read(byteArray);

            serverService.OnReceiveBattleInfo(sessionID, info);
            return true;
        }

        private static bool OnReceiveBattleSnapshot(int sessionID, ByteArray byteArray, IPokemonBattleServerService serverService)
        {
            var snapshot = DataByteArray.FromByteArray<BattleSnapshot>(byteArray);

            serverService.OnReceiveBattleSnapshot(sessionID, snapshot);
            return true;
        }

        #endregion
    }
}
